package com.my.lucky.util;

import com.my.lucky.model.Stock;

import java.util.ArrayList;
import java.util.List;

/**
 * MACD技术指标计算类
 * MACD = 快速EMA - 慢速EMA
 * 信号线 = MACD的EMA
 * 柱状图 = MACD - 信号线
 */
public class MACD {
    private final int fastPeriod; // 快速EMA周期，默认12
    private final int slowPeriod; // 慢速EMA周期，默认26
    private final int signalPeriod; // 信号线周期，默认9

    public MACD() {
        this(12, 26, 9);
    }

    public MACD(int fastPeriod, int slowPeriod, int signalPeriod) {
        this.fastPeriod = fastPeriod;
        this.slowPeriod = slowPeriod;
        this.signalPeriod = signalPeriod;
    }

    /**
     * 计算MACD指标
     *
     * @param stocks 股票列表
     * @return MACD结果，包含macd线、信号线和柱状图
     */
    public MACDResult calculateStock(List<Stock> stocks) {
        if (stocks == null || stocks.size() < slowPeriod) {
            throw new IllegalArgumentException("股票数据不足");
        }

        // 提取收盘价
        List<Double> prices = stocks.stream()
                .map(Stock::getClose)
                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

        // 计算MACD指标
        return calculate(prices);
    }

    /**
     * 计算MACD指标
     *
     * @param prices 价格序列
     * @return MACD结果，包含macd线、信号线和柱状图
     */
    public MACDResult calculate(List<Double> prices) {
        if (prices == null || prices.size() < slowPeriod) {
            throw new IllegalArgumentException("价格数据不足");
        }

        // 计算快速和慢速EMA
        List<Double> fastEMA = calculateEMA(prices, fastPeriod);
        List<Double> slowEMA = calculateEMA(prices, slowPeriod);

        // 计算MACD线
        List<Double> macdLine = new ArrayList<>();
        for (int i = 0; i < prices.size(); i++) {
            if (i < slowPeriod - 1) {
                macdLine.add(0.0);
                continue;
            }
            macdLine.add(fastEMA.get(i) - slowEMA.get(i));
        }

        // 计算信号线（MACD的9日EMA）
        List<Double> signalLine = calculateEMA(macdLine, signalPeriod);

        // 计算MACD柱状图
        List<Double> histogram = new ArrayList<>();
        for (int i = 0; i < macdLine.size(); i++) {
            if (i < signalPeriod - 1) {
                histogram.add(0.0);
                continue;
            }
            histogram.add(macdLine.get(i) - signalLine.get(i));
        }

        return new MACDResult(macdLine, signalLine, histogram);
    }

    /**
     * 计算指数移动平均线(EMA)
     */
    private List<Double> calculateEMA(List<Double> prices, int period) {
        List<Double> ema = new ArrayList<>();
        double multiplier = 2.0 / (period + 1);

        // 第一个EMA值使用简单平均
        double sum = 0;
        for (int i = 0; i < period && i < prices.size(); i++) {
            sum += prices.get(i);
        }
        ema.add(sum / period);

        // 计算后续的EMA值
        for (int i = period; i < prices.size(); i++) {
            double value = (prices.get(i) - ema.get(i - period)) * multiplier + ema.get(i - period);
            ema.add(value);
        }

        // 补充前面的空值
        while (ema.size() < prices.size()) {
            ema.add(0, 0.0);
        }

        return ema;
    }

    /**
     * MACD计算结果类
     */
    public static class MACDResult {
        private final List<Double> macdLine;    // MACD线
        private final List<Double> signalLine;  // 信号线
        private final List<Double> histogram;   // MACD柱状图

        public MACDResult(List<Double> macdLine, List<Double> signalLine, List<Double> histogram) {
            this.macdLine = macdLine;
            this.signalLine = signalLine;
            this.histogram = histogram;
        }

        public List<Double> getMacdLine() {
            return macdLine;
        }

        public List<Double> getSignalLine() {
            return signalLine;
        }

        public List<Double> getHistogram() {
            return histogram;
        }

        /**
         * 获取最新的MACD值
         */
        public double getLatestMACD() {
            return macdLine.get(macdLine.size() - 1);
        }

        /**
         * 获取最新的信号线值
         */
        public double getLatestSignal() {
            return signalLine.get(signalLine.size() - 1);
        }

        /**
         * 获取最新的柱状图值
         */
        public double getLatestHistogram() {
            return histogram.get(histogram.size() - 1);
        }

        /**
         * 判断是否为金叉（MACD线从下向上穿过信号线）
         */
        public boolean isGoldenCross() {
            if (macdLine.size() < 2) return false;
            int last = macdLine.size() - 1;
            return macdLine.get(last - 1) <= signalLine.get(last - 1)
                    && macdLine.get(last) > signalLine.get(last);
        }

        /**
         * 判断是否为死叉（MACD线从上向下穿过信号线）
         */
        public boolean isDeathCross() {
            if (macdLine.size() < 2) return false;
            int last = macdLine.size() - 1;
            return macdLine.get(last - 1) >= signalLine.get(last - 1)
                    && macdLine.get(last) < signalLine.get(last);
        }
    }
} 